//
//  HMStoreImage.m
//  ImageLoader
//
//  Created by Le Ngoc Thanh on 8/23/13.
//  Copyright (c) 2013 Le Ngoc Thanh. All rights reserved.
//

#import "HMStoreImage.h"

#define ImageFolder @"ImageFolder"
#define ImageStore  @"ImageStore"

#define SecsPerDay 86400.0f


@interface HMStoreImage(){
    NSMutableDictionary *managerUrl;
    NSNumber *indexFinalImage;
    NSCache *defaultCache;
}
@end
@implementation HMStoreImage

// Default queue to save data after download
+ (dispatch_queue_t) defaultSavequeue{
    static dispatch_queue_t defaultSavequeue = nil;
    if (defaultSavequeue == nil) {
        defaultSavequeue = dispatch_queue_create("vn.hm.defaultSavequeue", DISPATCH_QUEUE_SERIAL);
    }
    return defaultSavequeue;
}

// default manager
+ (HMStoreImage *)share{
    static HMStoreImage *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!manager) {
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsPath = [paths objectAtIndex:0];
            NSString *managerPath = [documentsPath stringByAppendingPathComponent:ImageStore];
            manager = [NSKeyedUnarchiver unarchiveObjectWithFile:managerPath];
            if (!manager) {
                manager = [[HMStoreImage alloc] init];
            }
        }
    });
    
    
    return manager;
}

#pragma mark - Create & save default
- (id)init
{
    self = [super init];
    if (self) {
        defaultCache = [[NSCache alloc] init];
        [self setUpNotification];
    }
    return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:managerUrl forKey:@"managerUrl"];
    [aCoder encodeObject:indexFinalImage forKey:@"indexFinalImage"];
    [aCoder encodeInt:_removeType forKey:@"removeType"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        managerUrl = [aDecoder decodeObjectForKey:@"managerUrl"];
        indexFinalImage = [aDecoder decodeObjectForKey:@"indexFinalImage"];
        _removeType = [aDecoder decodeIntForKey:@"removeType"];
        defaultCache = [[NSCache alloc] init];
        [self setUpNotification];
    }
    return self;
}

// save data
- (void)saveManager
{
    if (self) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsPath = [paths objectAtIndex:0];
        NSString *managerPath = [documentsPath stringByAppendingPathComponent:ImageStore];
        [NSKeyedArchiver archiveRootObject:self toFile:managerPath];
    }
}

#pragma mark - Cache Data
- (BOOL)saveData:(NSData *)data forOnlineUrl:(NSString *)online{
    __block BOOL isbool = NO;
    dispatch_sync([HMStoreImage defaultSavequeue], ^{
        if (data) {
            if (!indexFinalImage) {
                indexFinalImage = [NSNumber numberWithLongLong:0];
            }
            NSString *imageName = [NSString stringWithFormat:@"%llu_%f",[indexFinalImage longLongValue],[[NSDate date] timeIntervalSince1970]];
            NSString *stringUrl = [HMStoreImage saveImageFile:data withName:imageName isName:YES];
            if ([stringUrl length] > 0) {
                [self addLocalUrl:stringUrl forOnlineUrl:online];
                indexFinalImage = [NSNumber numberWithLongLong:[indexFinalImage longLongValue]+1];
                isbool = YES;
            }
        }
        isbool = NO;
        [self saveManager];
    });
    return isbool;
}
- (BOOL)saveData:(NSData *)data forOnlineUrl:(NSString *)online atLocalLink:(NSString *)local{
    __block BOOL isbool = NO;
    dispatch_sync([HMStoreImage defaultSavequeue], ^{
        if (data) {
            NSString *stringUrl = local;
            BOOL isName = NO;
            if (local) {
                if (!indexFinalImage) {
                    indexFinalImage = [NSNumber numberWithLongLong:0];
                }
                NSString *imageName = [NSString stringWithFormat:@"%llu_%f",[indexFinalImage longLongValue],[[NSDate date] timeIntervalSince1970]];
                stringUrl = imageName;
                isName = NO;
            }else{
                isName = YES;
            }
            
            stringUrl = [HMStoreImage saveImageFile:data withName:@"" isName:isName];
            if ([stringUrl length] > 0) {
                [self addLocalUrl:stringUrl forOnlineUrl:online];
                indexFinalImage = [NSNumber numberWithLongLong:[indexFinalImage longLongValue]+1];
                isbool = YES;
            }
        }
        isbool = NO;
        [self saveManager];
    });
    return isbool;
}

// save value is local link and key is online url
- (void)addLocalUrl:(NSString *)local forOnlineUrl:(NSString *)online{
    if (![[HMStoreImage share] isDownloaded:online]) {
        if (!managerUrl) {
            managerUrl = [[NSMutableDictionary alloc] init];
        }
        [managerUrl setValue:local forKey:online];
    }
}

// check folder is exist
+ (BOOL)isExistDirectory{
    NSString *strDir = [HMStoreImage defaultStoreImage];
    return [[NSFileManager defaultManager] fileExistsAtPath:strDir];
}

// save data with name to application's Document
+ (NSString *)saveImageFile:(NSData *)imageData withName:(NSString *)imageName isName:(BOOL)isName{
   NSString *str = imageName;
    if (isName) {
        NSString *strDir = [HMStoreImage defaultStoreImage];
        str = [NSString stringWithFormat:@"%@/%@",strDir,imageName];
        NSError *err;
        [[NSFileManager defaultManager] createDirectoryAtPath:strDir withIntermediateDirectories:NO attributes:nil error:&err];
    }
    BOOL isOK = [[NSFileManager defaultManager] createFileAtPath:str contents:imageData attributes:nil];
    if (!isOK) {
        return @"errrrrrrrrrrrrrr";
    }
    return str;
}
#pragma mark - remove data
- (void)removeFromOnlineLink:(NSString *)online{
    NSString *local = [self localFromOnlineString:online];
    NSArray *ar = [managerUrl allKeysForObject:local];
    [managerUrl removeObjectsForKeys:ar];
    [HMStoreImage removeFileInPath:local];
    [defaultCache removeObjectForKey:online];
}
- (void)removeLocal:(NSString *)local{
    NSArray *ar = [managerUrl allKeysForObject:local];
    [managerUrl removeObjectsForKeys:ar];
    [HMStoreImage removeFileInPath:local];
}

+ (void)removeAllImage{
    NSString *strDir = [HMStoreImage defaultStoreImage];
    NSError *err;
    NSArray *arr = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:strDir error:&err];
    if (err) {
        //NSLog(@"%@",err);
        //        return;
    }
    for (NSString *idString in arr) {
        NSString *local = [NSString stringWithFormat:@"%@/%@",strDir,idString];
        [[HMStoreImage share] removeLocal:local];
    }
}

+ (BOOL)removeFileInPath:(NSString *)path{
    return [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
}

#pragma mark - load local data
- (NSString *)localFromOnlineString:(NSString *)online{
    return [managerUrl objectForKey:online];
}

- (UIImage *)imageForOnlineUrl:(NSString *)online{
    UIImage *image = [defaultCache objectForKey:online];
    if (!image) {
        if ([self isDownloaded:online]) {
            NSString *str = [managerUrl objectForKey:online];
            NSData *data = [HMStoreImage dataformLocal:str];
            
            if (data) {
//                image = [UIImage imageWithData:data];
                image = [UIImage imageWithContentsOfFile:str];
                [defaultCache setObject:image forKey:online cost:data.length];
//                [defaultCache setObject:image forKey:online];
            }
        }
    }
    return image;
}

// get data from application's document
+ (NSData *)dataformLocal:(NSString *)local{
    return [[NSFileManager defaultManager] contentsAtPath:local];
}

// get image ID (name of file)
+ (NSString *)getIdImage:(NSString *)urlLocal{
    if ([urlLocal length] > 0) {
        NSString *strDir = [HMStoreImage defaultStoreImage];
        urlLocal = [urlLocal stringByReplacingOccurrencesOfString:strDir withString:@""];
    }
    return urlLocal;
}
#pragma mark - check data
- (BOOL)isDownloaded:(NSString *)online{
    NSString *str = [managerUrl objectForKey:online];
    return [[NSFileManager defaultManager] fileExistsAtPath:str];
}
#pragma mark - Utility
+ (NSString *)documentFolder{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsPath = [paths objectAtIndex:0];
    return documentsPath;
}

#pragma mark - remove manager

- (void)checkRemoveType{
    BOOL isExist = [HMStoreImage isExistDirectory];
    if (!isExist) {
        return;
    }
    switch (_removeType) {
        case HMStoreImageAutoRemoveNone:{
            // don't do nothing
            break;
        }
        case HMStoreImageAutoRemoveStartApp:{
            // comming soon
            [HMStoreImage removeAllImage];
            break;
        }
        case HMStoreImageAutoRemoveOldData_ThreeDays:{
            // clear old data when app start
            [self removeDataOlderThan:SecsPerDay*3];
            break;
        }
        default:
            break;
    }
}

// remove older image
- (void)removeDataOlderThan:(NSTimeInterval)secs{
    NSTimeInterval oldSecs = [[NSDate date] timeIntervalSince1970] - secs;
    NSString *strDir = [HMStoreImage defaultStoreImage];
    NSError *err;
    NSArray *arr = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:strDir error:&err];
    if (err) {
        //NSLog(@"%@",err);
        //        return;
    }
    for (NSString *idString in arr) {
        NSArray *arr = [idString componentsSeparatedByString:@"_"];
        if ([[arr objectAtIndex:1] doubleValue] < oldSecs) {
            NSString *local = [NSString stringWithFormat:@"%@/%@",strDir,idString];
            [[HMStoreImage share] removeLocal:local];
        }
    }
}
#pragma mark - Notification

- (void)setUpNotification{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiverMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}
- (void)receiverMemoryWarning{
    NSLog(@"receiverMemoryWarning");
    [defaultCache removeAllObjects];
    
}
+ (NSString *)defaultStoreImage{
//    NSString *strDir = [NSString stringWithFormat:@"%@/%@/",[HMStoreImage documentFolder],ImageFolder];
    NSString *strDir = [NSString stringWithFormat:@"%@/%@/%@/%@",[HMStoreImage documentFolder],ResourceFolder,AssetFolder,@"cmo"];
    return strDir;
}
@end
